package com.swak.vertx.protocol.http.adapter;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.BiConsumer;

import com.swak.entity.Result;
import com.swak.vertx.cache.GlobalCacheService;

/**
 * 获取缓存
 * 
 * @author lifeng
 */
public class MethodCacheAdapter extends AbstractAdapter {

	private GlobalCacheService cacheStorage;
	private final BiConsumer<Context, Throwable> handle;

	public MethodCacheAdapter(GlobalCacheService cacheStorage) {
		this.cacheStorage = cacheStorage;
		this.handle = this::handle;
	}

	@Override
	public CompletionStage<Context> handle(Context context) {
		CompletionStage<Object> future = this.cacheStorage.getObject(context.$method.getMethodCache().name());
		if (future != null) {
			return future.thenCompose(result -> {
				if (result != null) {
					context.$result = result;
					return CompletableFuture.completedFuture(context);
				}
				return this.next(context);
			}).exceptionally(e -> {
				context.$error = e;
				return context;
			});
		}
		return this.next(context);
	}

	@Override
	protected CompletionStage<Context> next(Context context) {
		CompletionStage<Context> nextFuture = super.next(context);
		nextFuture.whenComplete(this.handle);
		return nextFuture;
	}

	protected void handle(Context context, Throwable error) {
		if (context.$method.getMethodCache() != null && this.cacheStorage != null && error == null
				&& context.$result != null && context.$result instanceof Result
				&& ((Result) context.$result).isSuccess()) {
			this.cacheStorage.putObject(context.$method.getMethodCache().name(), context.$result,
					context.$method.getMethodCache().timeToIdle());
		}
	}

}
